import time
#from threading import Thread
import threading
import numpy as np
import pandas as pd
import sqlite3
from tqsdk import TqApi, TqAuth, TqKq
from MyTT import EMA, SUM
from rich.console import Console
from rich.theme import Theme
from MyTT import REF, EMA

# 定义颜色主题
custom_theme = Theme({
    "info": "cyan",
    "warning": "yellow",
    "error": "red",
    "success": "green",
    "trade": "bold magenta"
})
console = Console(theme=custom_theme)

# 定义全局变量
symbols = []
api=None
threads = None
stop_event = threading.Event()
# api = TqApi(account=TqKq(), auth=TqAuth("cps168", "alibaba"))



def get_symbols():
    try:
        conn = sqlite3.connect('trade_monitor.db')
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM products WHERE is_monitored=1")
        products = cursor.fetchall()
        conn.close()
        symbols=[row[2] for row in products]
    except Exception as e:
        print(f"从数据库获取监控品种时出错: {e}", style="error")
    return symbols

def stop_loss(symbol):
        console.print(f"{time.strftime('%X')} 开始检查{symbol}止损条件", style="warning")
        klines = api.get_kline_serial(symbol, 60,data_length=300)
        position = api.get_position(symbol)
        console.print(f"{time.strftime('%X')} 开始处理 {symbol}", style="warning") 
        #api.wait_update(deadline=time.time() + 1)
        if True:#api.is_changing(klines, "datetime"):
                console.print(f"{time.strftime('%X')} 数据更新", style="info")
                try:
                    close = klines.close
                    low = klines.low
                    open = klines.open
                    high = klines.high
                    # 转换为 numpy 数组，方便使用 MyTT 计算
                    close = np.array(close)
                    low = np.array(low)
                    open = np.array(open)
                    high = np.array(high)

                    Q = (3 * close + low + open + high) / 6
                    # 计算操盘线
                    trading_line = (26 * Q + 25 * REF(Q, 1) + 24 * REF(Q, 2) + 23 * REF(Q, 3) + 22 * REF(Q, 4) + 21 * REF(Q, 5) + 20 * REF(Q, 6) + 19 * REF(Q, 7) + 18 * REF(Q, 8) + 17 * REF(Q, 9) + 16 * REF(Q, 10) + 15 * REF(Q, 11) + 14 * REF(Q, 12) + 13 * REF(Q, 13) + 12 * REF(Q, 14) + 11 * REF(Q, 15) + 10 * REF(Q, 16) + 9 * REF(Q, 17) + 8 * REF(Q, 18) + 7 * REF(Q, 19) + 6 * REF(Q, 20) + 5 * REF(Q, 21) + 4 * REF(Q, 22) + 3 * REF(Q, 23) + 2 * REF(Q, 24) + REF(Q, 26)) / 351
                    # 计算空头线
                    short_line = EMA(trading_line, 7)
                    # 平仓条件判断
                    print("条件值是：",trading_line[-2],short_line[-2])
                    if len(trading_line) >= 2 and len(short_line) >= 2:
                        if position.pos_short > 0 and trading_line[-2] > short_line[-2]:
                            if symbol.startswith('SHFE'):
                                # 平今仓
                                if position.pos_short_today > 0:
                                    api.insert_order(
                                        symbol=symbol,
                                        direction="BUY",
                                        offset="CLOSETODAY",
                                        volume=position.pos_short_today
                                    )
                                    console.print(
                                        f"{time.strftime('%X')} 平SHFE{symbol}今空仓: 手数: {position.pos_short_today}",
                                        style="trade"
                                    )
                                # 平昨仓
                                if position.pos_short_his > 0:
                                    api.insert_order(
                                        symbol=symbol,
                                        direction="BUY",
                                        offset="CLOSEYESTERDAY",
                                        volume=position.pos_short_his
                                    )
                                    console.print(
                                        f"{time.strftime('%X')} 平SHFE{symbol}昨空仓: 手数: {position.pos_short_his}",
                                        style="trade"
                                    )
                            else:
                                api.insert_order(
                                    symbol=symbol,
                                    direction="BUY",
                                    offset="CLOSE",
                                    volume=position.pos_short
                                )
                                console.print(
                                    f"{time.strftime('%X')} 平{symbol}空仓: 手数: {position.pos_short}",
                                    style="trade"
                                )

                        if position.pos_long > 0 and trading_line[-2] < short_line[-2]:
                            if symbol.startswith('SHFE'):
                                # 平今仓
                                if position.pos_long_today > 0:
                                    api.insert_order(
                                        symbol=symbol,
                                        direction="SELL",
                                        offset="CLOSETODAY",
                                        volume=position.pos_long_today
                                    )
                                    console.print(
                                        f"{time.strftime('%X')} 平SHFE{symbol}今多仓: 手数: {position.pos_long_today}",
                                        style="trade"
                                    )
                                # 平昨仓
                                if position.pos_long_his > 0:
                                    api.insert_order(
                                        symbol=symbol,
                                        direction="SELL",
                                        offset="CLOSEYESTERDAY",
                                        volume=position.pos_long_his
                                    )
                                    console.print(
                                        f"{time.strftime('%X')} 平SHFE{symbol}昨多仓: 手数: {position.pos_long_his}",
                                        style="trade"
                                    )
                            else:
                                api.insert_order(
                                    symbol=symbol,
                                    direction="SELL",
                                    offset="CLOSE",
                                    volume=position.pos_long
                                )
                                console.print(
                                    f"{time.strftime('%X')} 平{symbol}多仓: 手数: {position.pos_long}",
                                    style="trade"
                                )
                except Exception as e:
                    console.print(f"处理 {symbol} 止损逻辑时出错: {e}", style="error")   

if __name__ == "__main__":
    try:
        api = TqApi(account=TqKq(), auth=TqAuth("cps168", "alibaba"))
        symbols = get_symbols()
        for symbol in symbols:
            thread=threading.Thread(target=stop_loss,args=(symbol,),daemon=True)
            thread.start()
            threads.append(thread)
            time.sleep(2)

    # except Exception as e:
    #     console.print(f"程序运行出错: {e}", style="error")   
        while True:
            api.wait_update(deadline=time.time() + 1)
    except KeyboardInterrupt:
        api.close()
        console.print("主线程被用户中断，正在等待子线程结束...", style="info")
        for Thread in threads:
            Thread.join()
        console.print("所有子线程已结束，程序退出。", style="success")
    finally:
        api.close()


